/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.icanci.coupon.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.icanci.basic.commonutils.R;
import cn.icanci.basic.exception.ApplicationException;
import cn.icanci.coupon.client.TradeLogService;
import cn.icanci.coupon.entity.CouponEntity;
import cn.icanci.coupon.factory.CouponFactory;
import cn.icanci.coupon.form.BeCouponForm;
import cn.icanci.coupon.form.CouponVO;
import cn.icanci.coupon.form.OptionModule;
import cn.icanci.coupon.mapper.CouponMapper;
import cn.icanci.coupon.mapper.CouponRecordMapper;
import cn.icanci.coupon.model.Coupon;
import cn.icanci.coupon.model.CouponRecord;
import cn.icanci.coupon.service.CouponService;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;

/**
 * @author icanci
 * @date Created in 2021/05/01 11:26
 * @version 1.0
 */
@Slf4j
@Service
public class CouponServiceImpl implements CouponService {
    @Resource
    private CouponFactory      couponFactory;
    @Resource
    private CouponMapper       couponMapper;
    @Resource
    private CouponRecordMapper couponRecordMapper;
    @Resource
    private TradeLogService    tradeLogService;

    /**
     * 保存优惠券
     * @param beCouponForm 页面对象
     */
    @Override
    public void addCoupons(BeCouponForm beCouponForm) {
        CouponEntity couponEntity = couponFactory.create(beCouponForm);
        couponEntity.saveCoupon(couponEntity);
    }

    /**
     * 查询所有优惠券
     * @return 返回查询的优惠券
     */
    @Override
    public List<CouponVO> searchAllCoupons() {
        List<CouponVO> couponList = Lists.newArrayList();
        List<String> unkList = couponMapper.searchAllByUniqueKey();
        if (CollectionUtil.isEmpty(unkList)) {
            return couponList;
        }
        for (String unk : unkList) {
            CouponVO couponVO = new CouponVO();
            Coupon coupon = couponMapper.queryOneByUnk(unk);
            BeanUtils.copyProperties(coupon, couponVO);
            int occupyCount = couponMapper.queryOccupyByUnk(unk);
            couponVO.setOccupyCount(occupyCount);
            int usedCount = couponMapper.queryUsedByUnk(unk);
            couponVO.setUsedCount(usedCount);
            int onlineCount = couponMapper.queryOnlineByUnk(unk);
            couponVO.setOnlineCount(onlineCount);
            couponList.add(couponVO);
        }
        return couponList;
    }

    /**
     * 更新一条记录
     * @param uniqueKey 优惠券号码
     * @param userId 用户唯一id
     */
    @Override
    @Transactional(rollbackFor = ApplicationException.class)
    public R insertOneCoupon(String uniqueKey, Integer userId) {
        try {
            CouponEntity couponEntity = couponFactory.create(uniqueKey);
            couponEntity.updateStatusOccupy();
            couponEntity.inertOneUserRecord(userId);
            tradeLogService.info(log, "插入成功，userId:{},couponNumber:{}", userId, couponEntity.getCouponNumber());
            return R.ok().message("优惠券已经入手了~");
        } catch (ApplicationException e) {
            tradeLogService.error(log, "优惠券已经抢完啦，message:{}", e.getMsg());
            return R.error().message("查询错误，" + e.getMsg());
        }
    }

    /**
     * 更新一条记录
     * @param couponNumber 优惠券号码
     * @param userId 用户唯一id
     * @return
     */
    @Override
    public R updateOneCoupon(String couponNumber, Integer userId) {
        try {
            CouponEntity couponEntity = couponFactory.createByCouponNumber(couponNumber);
            couponEntity.updateStatusOrder();
            couponEntity.updateOneUserRecord(userId);
            tradeLogService.info(log, "更新状态成功，userId:{},couponNumber:{}", userId, couponNumber);
            return R.ok().message("成功~");
        } catch (ApplicationException e) {
            tradeLogService.error(log, "查询错误，message:{}", e.getMsg());
            return R.error().message("查询错误，" + e.getMsg());
        }
    }

    /**
     * 查询所有的券的唯一标识
     * @return
     */
    @Override
    public List<OptionModule> searchCouponListUNK() {
        List<String> lists = couponMapper.searchAllByUniqueKey();
        List<OptionModule> optionModules = Lists.newArrayList();
        if (CollectionUtil.isEmpty(lists)) {
            return optionModules;
        }
        for (String s : lists) {
            OptionModule optionModule = new OptionModule();
            optionModule.setLabel(s);
            optionModule.setValue(s);
            optionModules.add(optionModule);
        }
        return optionModules;
    }

    /**
     * 查询所有
     * @param unk
     * @return
     */
    @Override
    public List<Coupon> searchOneCouponListByUNK(String unk) {
        return couponMapper.queryAllByUnk(unk);
    }

    /**
     * 条件查询
     * @param condition
     * @return
     */
    @Override
    public List<CouponVO> searchAllCouponsByCondition(String condition) {
        List<String> lists = couponMapper.searchAllByUniqueKey();
        List<CouponVO> couponVOS = Lists.newArrayList();
        if (CollectionUtil.isEmpty(lists)) {
            return couponVOS;
        }
        for (String unk : lists) {
            CouponVO couponVO = couponMapper.queryOneByCondition(unk, condition);
            int occupyCount = couponMapper.queryOccupyByUnk(unk);
            if (null == couponVO){
                continue;
            }
            couponVO.setOccupyCount(occupyCount);
            int usedCount = couponMapper.queryUsedByUnk(unk);
            couponVO.setUsedCount(usedCount);
            int onlineCount = couponMapper.queryOnlineByUnk(unk);
            couponVO.setOnlineCount(onlineCount);
            if (null != condition) {
                couponVOS.add(couponVO);
            }
        }
        return couponVOS;
    }

    /**
     * 根据时间查询
     * @return
     */
    @Override
    public List<CouponVO> searchAllCouponsLimitTime() {
        List<CouponVO> couponList = Lists.newArrayList();
        List<String> unkList = couponMapper.searchAllByUniqueKey();
        if (CollectionUtil.isEmpty(unkList)) {
            return couponList;
        }
        for (String unk : unkList) {
            CouponVO couponVO = new CouponVO();
            Coupon coupon = couponMapper.searchAllCouponsLimitTime(unk, new Date());
            if (null == coupon) {
                continue;
            }
            BeanUtils.copyProperties(coupon, couponVO);
            int occupyCount = couponMapper.queryOccupyByUnk(unk);
            couponVO.setOccupyCount(occupyCount);
            int usedCount = couponMapper.queryUsedByUnk(unk);
            couponVO.setUsedCount(usedCount);
            int onlineCount = couponMapper.queryOnlineByUnk(unk);
            couponVO.setOnlineCount(onlineCount);
            couponList.add(couponVO);
        }
        return couponList;
    }

    /**
     * 查询一个用户的优惠券数据
     * @param userId
     * @return
     */
    @Override
    public R queryUserCoupons(Integer userId) {
        List<CouponRecord> couponRecords = couponRecordMapper.findManyByUserId(userId);
        if (CollectionUtil.isEmpty(couponRecords)) {
            return R.error().message("您暂时没有优惠券嗷~");
        }
        List<Coupon> couponList = Lists.newArrayList();
        for (CouponRecord record : couponRecords) {
            String couponNumber = record.getCouponNumber();
            Coupon oneByCouponNumber = couponMapper.findOneByCouponNumber(couponNumber);
            if (null != oneByCouponNumber) {
                oneByCouponNumber.setCreateTime(record.getCreateTime());
                couponList.add(oneByCouponNumber);
            }
        }
        return R.ok().message("查询成功~").data("couponList", couponList);
    }

    /**
     * 查询一个用户的优惠券数据
     * @param userId
     * @param startCity
     * @param endCity
     * @return
     */
    @Override
    public R queryUserCouponsByTargetSECity(Integer userId, String startCity, String endCity) {
        List<CouponRecord> couponRecords = couponRecordMapper.findManyByUserId(userId);
        if (CollectionUtil.isEmpty(couponRecords)) {
            return R.error().message("您暂时没有优惠券嗷~");
        }
        List<Coupon> couponList = Lists.newArrayList();
        for (CouponRecord record : couponRecords) {
            String couponNumber = record.getCouponNumber();
            Coupon oneByCouponNumber = couponMapper.findOneByCouponNumber(couponNumber);
            if (null != oneByCouponNumber && startCity.equals(oneByCouponNumber.getStartCity()) && endCity.equals(oneByCouponNumber.getEndCity())) {
                oneByCouponNumber.setCreateTime(record.getCreateTime());
                couponList.add(oneByCouponNumber);
            }
        }
        if (CollectionUtil.isEmpty(couponList)) {
            return R.error().message("您暂时没有合适的优惠券嗷~");
        }
        return R.ok().message("查询成功~").data("couponList", couponList);
    }

    /**
     * 查询用户的一条优惠券信息
     * @param couponNumber
     * @param userId
     * @return
     */
    @Override
    public R queryOneCoupon(String couponNumber, Integer userId) {
        CouponRecord couponRecord = couponRecordMapper.findOneByCouponNumberAndUserId(couponNumber, userId);
        if (null == couponRecord) {
            return R.error().message("此记录不存在");
        }
        Coupon oneByCouponNumber = couponMapper.findOneByCouponNumber(couponNumber);
        if (null == couponNumber) {
            return R.error().message("此记录不存在");
        }
        return R.ok().message("查询成功").data("coupon", oneByCouponNumber);
    }
}
